<template>
  <div
    ref="containerRef"
    class="login-wrap"
    :style="{
      backgroundImage: `url(${pageBgUrl})`,
    }"
  >
    <canvas id="canvas"></canvas>
    <!-- 登录 -->
    <!-- 
      @mousedown="onTouchstart"
     -->
    <div
      :style="{
        transition: `all ${dataMap.transitionTime}s ease-out`,
        transform: `translate(${dataMap.translateX}px, ${dataMap.translateY}px)`,
      }"
      class="ms-login"
    >
      <div class="ms-title">日报管理系统</div>

      <el-form
        :model="formData"
        :rules="rules"
        ref="login"
        label-width="0px"
        size="large"
        class="ms-content"
      >
        <el-form-item prop="username">
          <el-input
            ref="usernameRef"
            v-model="formData.username"
            placeholder="用户名"
            maxlength="16"
            clearable
            @keyup.enter="focusInput('passwordRef')"
          >
            <template #prepend>
              <user class="icon" @click="focusInput('usernameRef')" />
            </template>
          </el-input>
        </el-form-item>

        <el-form-item prop="password">
          <el-input
            ref="passwordRef"
            type="password"
            show-password
            placeholder="密码"
            v-model="formData.password"
            maxlength="18"
            clearable
            @keyup.enter="onPasswordEnter"
          >
            <template #prepend>
              <lock class="icon" @click="focusInput('passwordRef')" />
            </template>
          </el-input>
        </el-form-item>

        <el-form-item v-if="isRegist" prop="repeatPassword">
          <el-input
            ref="repeatPasswordRef"
            type="password"
            show-password
            placeholder="重复密码"
            v-model="formData.repeatPassword"
            maxlength="18"
            clearable
            @keyup.enter="focusInput('nicknameRef')"
          >
            <template #prepend>
              <lock class="icon" @click="focusInput('repeatPasswordRef')" />
            </template>
          </el-input>
        </el-form-item>

        <el-form-item v-if="isRegist" prop="nickname">
          <el-input
            ref="nicknameRef"
            v-model="formData.nickname"
            placeholder="你的昵称"
            maxlength="16"
            clearable
            @keyup.enter="submitFormMethod"
          >
            <template #prepend>
              <user class="icon" @click="focusInput('nicknameRef')" />
            </template>
          </el-input>
        </el-form-item>

        <div class="login-btn">
          <el-button
            type="primary"
            @click="submitFormMethod"
            :loading="submitLoading"
          >
            {{ isRegist ? "注册" : "登录" }}
          </el-button>
        </div>

        <p v-if="isRegist" class="login-tips">
          提示 : 已经注册？点击开始
          <span
            style="color: #67c23a; cursor: pointer"
            @click="toggleRegMethod"
          >
            登录
          </span>
        </p>
        <p v-else class="login-tips">
          提示 : 还没注册？点击开始
          <span
            style="color: #67c23a; cursor: pointer"
            @click="toggleRegMethod"
          >
            注册
          </span>
        </p>
      </el-form>
      <div class="puzzle_box">
        <PuzzleVerification
          v-model:modelValue="isVerificationShow"
          :puzzleImgList="puzzleImgList"
          @success="loginMethod"
          @close="submitLoading = false"
        />
      </div>
    </div>
  </div>
</template>

<script>
import { ref, reactive, getCurrentInstance, onUnmounted, onMounted } from "vue";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { REMEMBER_PASSWORD } from "../../utils/keysManage/localKeys";
// import { setCookie, getCookie } from "../../utils/cookies";
import { encryptData, decryptData } from "../../utils/crypto";
import { getRandom } from "../../utils/common";
import PuzzleVerification from "../../components/puzzleVerification.vue";

// 图片静态资源
import bg1 from "../../assets/img/2022_bg/2022_bg_0.jpg";
import bg2 from "../../assets/img/2022_bg/2022_bg_1.jpg";
import bg3 from "../../assets/img/2022_bg/2022_bg_2.jpg";
import bg4 from "../../assets/img/2022_bg/2022_bg_3.jpg";
// import bg5 from "../../assets/img/2022_bg/2022_bg_4.jpg";
import bg6 from "../../assets/img/2022_bg/2022_bg_5.jpg";
import bg7 from "../../assets/img/2022_bg/2022_bg_6.jpg";
import bg8 from "../../assets/img/2022_bg/2022_bg_7.jpg";
import bg9 from "../../assets/img/2022_bg/2022_bg_8.jpg";
// import bg10 from "../../assets/img/2022_bg/2022_bg_9.jpg";
import bg11 from "../../assets/img/2022_bg/2022_bg_10.jpg";
import bg12 from "../../assets/img/2022_bg/2022_bg_11.jpg";
import bg13 from "../../assets/img/2022_bg/2022_bg_12.jpg";
import bg14 from "../../assets/img/2022_bg/2022_bg_13.jpg";
// import bg15 from "../../assets/img/2022_bg/2022_bg_14.jpg";
import bg16 from "../../assets/img/2022_bg/2022_bg_15.jpg";
// import bg17 from "../../assets/img/2022_bg/2022_bg_16.jpg";

// 烟花
import Fireworks from "../../utils/fireworks";

import puzzleImg01 from "../../assets/img/puzzle/01.png";
import puzzleImg02 from "../../assets/img/puzzle/02.png";
import puzzleImg03 from "../../assets/img/puzzle/03.png";
import puzzleImg04 from "../../assets/img/puzzle/04.png";
import puzzleImg05 from "../../assets/img/puzzle/05.png";
import puzzleImg06 from "../../assets/img/puzzle/06.png";
import puzzleImg07 from "../../assets/img/puzzle/07.png";
import puzzleImg08 from "../../assets/img/puzzle/08.png";
import puzzleImg09 from "../../assets/img/puzzle/09.png";
import puzzleImg10 from "../../assets/img/puzzle/10.png";
import puzzleImg11 from "../../assets/img/puzzle/11.png";

const imgArr = [
  bg1,
  bg2,
  bg3,
  bg4,
  // bg5,
  bg6,
  bg7,
  bg8,
  bg9,
  // bg10,
  bg11,
  bg12,
  bg13,
  bg14,
  // bg15,
  bg16,
  // bg17,
];

let timer = null;
const scrollTimer = null;

const puzzleImgList = [
  puzzleImg01,
  puzzleImg02,
  puzzleImg03,
  puzzleImg04,
  puzzleImg05,
  puzzleImg06,
  puzzleImg07,
  puzzleImg08,
  puzzleImg09,
  puzzleImg10,
  puzzleImg11,
];

export default {
  components: { PuzzleVerification },
  setup(props, context) {
    const { proxy } = getCurrentInstance();
    const $api = proxy.$api;
    const router = useRouter();
    const store = useStore();

    // 表单绑定的数据
    const formData = reactive({
      username: "",
      password: "",
      repeatPassword: "",
      nickname: "",
    });

    // 是否是注册，默认否
    const isRegist = ref(false);

    const dataMap = reactive({
      transitionTime: 0.5,
      translateX: 0,
      translateY: 0,
    });

    let startX = 0;
    let startY = 0;

    // 触摸中
    const onTouchmove = (e) => {
      // console.log('触摸中 ===>', e)
      dataMap.translateX = e.pageX - startX;
      dataMap.translateY = e.pageY - startY;
    };

    // 结束触摸
    const onTouchend = (e) => {
      // console.log('结束触摸 ===>', e)
      dataMap.transitionTime = 0.5;
      dataMap.translateX = 0;
      dataMap.translateY = 0;
      window.removeEventListener("mousemove", onTouchmove);
      window.removeEventListener("mouseup", onTouchend);
    };

    // 开始触摸
    const onTouchstart = (e) => {
      // console.log('开始触摸 ===>', e)
      dataMap.transitionTime = 0;
      startX = e.pageX;
      startY = e.pageY;
      window.addEventListener("mousemove", onTouchmove);
      window.addEventListener("mouseup", onTouchend);
    };

    // 记住密码（方便登录）
    let rememberPassword = window.localStorage.getItem(REMEMBER_PASSWORD);
    if (rememberPassword) {
      rememberPassword = JSON.parse(rememberPassword);
      formData.username = rememberPassword.username || "";
      formData.password = decryptData(rememberPassword.password);
    }

    // 表单校验规则
    const rules = reactive({
      username: [
        {
          required: true,
          message: "请输入用户名",
          trigger: "blur",
        },
      ],
      password: [{ required: true, message: "请输入密码", trigger: "blur" }],
      repeatPassword: [
        {
          required: isRegist.value,
          trigger: "blur",
          validator: (rule, value, callback) => {
            if (!value) {
              callback(new Error("请重复输入密码"));
            } else if (value !== formData.password) {
              callback(new Error("重复密码不一致"));
            } else {
              callback();
            }
          },
        },
      ],
      nickname: [
        {
          required: isRegist.value,
          trigger: "blur",
          validator: (rule, value, callback) => {
            if (!value) {
              callback(new Error("请输入你的昵称"));
            } else {
              callback();
            }
          },
        },
      ],
    });

    const login = ref(null);
    const submitLoading = ref(false);

    // 拼图验证
    const isVerificationShow = ref(false);

    const toggleRegMethod = () => {
      if (submitLoading.value) return;
      isRegist.value = !isRegist.value;
    };

    // 提交表单
    const submitFormMethod = () => {
      if (submitLoading.value) return;
      login.value.validate((valid) => {
        if (valid) {
          submitLoading.value = true;
          if (isRegist.value) {
            regMethod();
          } else {
            isVerificationShow.value = true;
          }
        }
      });
    };

    const regMethod = () => {
      $api.users
        .reg(formData)
        .then((res) => {
          ElMessage.success("注册成功，请登录！");
          submitLoading.value = false;
          toggleRegMethod();
        })
        .catch((err) => {
          submitLoading.value = false;
          console.error("reg error: ", err);
        });
    };

    const loginMethod = () => {
      $api.users
        .login(formData)
        .then((res) => {
          ElMessage.success("登录成功");
          window.localStorage.setItem(
            REMEMBER_PASSWORD,
            JSON.stringify({
              username: formData.username || "",
              password: encryptData(formData.password),
            })
          );
          store.commit("user/login", res.data);
          router.replace("/");
        })
        .catch((err) => {
          console.error("login error: ", err);
        })
        .finally(() => {
          submitLoading.value = false;
        });
    };

    const usernameRef = ref(null);
    const passwordRef = ref(null);
    const repeatPasswordRef = ref(null);
    const nicknameRef = ref(null);
    const focusInput = (refKey) => {
      switch (refKey) {
        case "usernameRef":
          usernameRef.value.focus();
          break;
        case "passwordRef":
          passwordRef.value.focus();
          break;
        case "repeatPasswordRef":
          repeatPasswordRef.value.focus();
          break;
        case "nicknameRef":
          nicknameRef.value.focus();
          break;
      }
    };

    // 密码输入框回车事件
    const onPasswordEnter = () => {
      if (isRegist.value) {
        focusInput("repeatPasswordRef");
      } else {
        submitFormMethod();
      }
    };

    const containerRef = ref(null);

    // 随机背景图
    const pageBgIndex = getRandom(0, imgArr.length - 1, true);
    const pageBgUrl = ref(imgArr[pageBgIndex]);

    // 烟花背景参数
    const fireworksData = {
      canvas: "",
      ctx: "",
      canvasWidth: "",
      canvasHeight: "",
      fworks: null,
      lastTime: "",
      newTime: "",
    };

    const initFireworks = (w, h) => {
      fireworksData.fworks = new Fireworks(w, h);
      fireworksData.lastTime = new Date();
      animateStart();
    };

    const animateStart = () => {
      timer = window.requestAnimFrame(animateStart);
      fireworksData.newTime = new Date();
      if (
        fireworksData.newTime - fireworksData.lastTime >
        800 + (fireworksData.canvasHeight - 2200) / 2
      ) {
        fireworksData.fworks.color = Math.random() * 10 > 2 ? 1 : 0;
        const x = getRandom(
          fireworksData.canvasWidth / 10,
          (fireworksData.canvasWidth * 9) / 10
        );
        const y = getRandom(50, (fireworksData.canvasHeight * 2) / 3);
        const bigboom = fireworksData.fworks.createFireworks(
          x,
          fireworksData.canvasHeight,
          x,
          y
        );
        fireworksData.lastTime = fireworksData.newTime;
      }
    };

    onMounted(() => {
      fireworksData.canvas = document.getElementById("canvas");
      fireworksData.canvas.width = fireworksData.canvasWidth =
        containerRef.value.offsetWidth;
      fireworksData.canvas.height = fireworksData.canvasHeight =
        containerRef.value.offsetHeight;
      // console.log("fireworksData.canvasWidth", fireworksData.canvasWidth);
      // console.log("fireworksData.canvasHeight", fireworksData.canvasHeight);
      initFireworks(fireworksData.canvasWidth, fireworksData.canvasHeight);
    });

    onUnmounted(() => {
      if (scrollTimer) clearInterval(scrollTimer);
      if (timer) window.cancelAnimationFrame(timer);
    });

    // 清除缓存的标签导航
    store.commit("clearTags");

    return {
      formData, // 表单绑定的数据
      rules, // 表单校验规则
      login, // 表单的引用
      submitLoading, // 提交按钮的loading状态
      isRegist, // 是否是注册，默认否
      submitFormMethod, // 提交表单
      toggleRegMethod, // 切换登录/注册
      regMethod, // 注册
      loginMethod, // 登录
      usernameRef,
      passwordRef,
      repeatPasswordRef,
      nicknameRef,
      focusInput,
      onPasswordEnter,
      pageBgUrl,
      containerRef,
      isVerificationShow,
      puzzleImgList,
      dataMap,
      onTouchstart,
    };
  },
};
</script>

<style lang="less" scoped>
.login-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  background-image: url(../../assets/img/login-bg.jpg);
  background-size: 100%;
  background-position: center center;
}
.ms-title {
  margin: 0 30px;
  line-height: 60px;
  text-align: center;
  font-size: 20px;
  letter-spacing: 1px;
  color: #fff;
  border-bottom: 1px solid rgba(233, 233, 233, 0.3);
  user-select: none;
  text-shadow: 2px 2px rgba(0, 0, 0, 0.25);
}
.ms-login {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 90;
  width: 350px;
  margin: -190px 0 0 -175px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(5px);
  // overflow: hidden;
  &:hover {
    box-shadow: rgba(0, 0, 0, 0.12) 0px 0px 12px 0px;
  }
}
.ms-content {
  padding: 22px 30px 40px;
}
.login-btn {
  text-align: center;
}
.login-btn button {
  width: 100%;
  height: 36px;
  margin-bottom: 22px;
}
.login-tips {
  font-size: 12px;
  line-height: 30px;
  color: #666;
  background-color: #fff;
  text-align: center;
  border-radius: 15px;
}
.icon {
  // color: #f56c6c;
  cursor: pointer;
  width: 1.2em;
  height: 1.2em;
}

#canvas {
  width: 100%;
  height: 100%;
}

.puzzle_box {
  position: absolute;
  top: -30px;
  left: 50%;
  transform: translateX(-50%);
}
</style>
